package config

import (
	"encoding/json"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

type Config struct {
	WindowWidth     int     `json:"window_width,omitempty"`  //屏幕宽
	WindowHeight    int     `json:"window_height,omitempty"` //屏幕高
	WindowTitle     string  `json:"window_title,omitempty"`  //标题
	TicksPerSecond  int     `json:"ticks_per_second,omitempty"`
	VsyncEnabled    bool    `json:"vsync_enabled,omitempty"`
	RunInBackground bool    `json:"run_in_background,omitempty"`
	SfxVolume       float64 `json:"sfx_volume,omitempty"`
	BgmVolume       float64 `json:"bgm_volume,omitempty"`
	FullScreen      bool    `json:"full_screen,omitempty"`

	path string
}

func defaultConfig() *Config {
	cfg := Config{
		WindowWidth:     1024,
		WindowHeight:    768,
		WindowTitle:     "火种与文明",
		TicksPerSecond:  60,
		VsyncEnabled:    true,
		RunInBackground: true,
		FullScreen:      false,
		SfxVolume:       1,
		BgmVolume:       1,
	}

	return &cfg
}

// Configuration defines the configuration for the engine, loaded from config.json
func Load(json_path string) (*Config, error) {
	cfg := Config{}

	buf, e := os.ReadFile(json_path)
	if e != nil {
		cfg = *defaultConfig()
	}

	e = json.Unmarshal(buf, &cfg)
	if e != nil {
		cfg = *defaultConfig()
	}

	return &cfg, nil
}

// Save saves the configuration object to disk
func (cfg *Config) Save() error {
	configDir := filepath.Dir(cfg.path)
	if e := os.MkdirAll(configDir, 0750); e != nil {
		return errors.Wrap(e, "MkdirAll")
	}

	configFile, e := os.Create(cfg.path)
	defer configFile.Close()
	if e != nil {
		return errors.Wrap(e, "Create")
	}

	buf, e := json.MarshalIndent(cfg, "", "  ")
	if e != nil {
		return errors.Wrap(e, "MarshalIndent")
	}

	if _, e := configFile.Write(buf); e != nil {
		return errors.Wrap(e, "Write")
	}

	return nil
}

// Dir returns the directory component of the path
func (cfg *Config) Dir() string {
	return filepath.Dir(cfg.path)
}

// Base returns the base component of the path
func (cfg *Config) Base() string {
	return filepath.Base(cfg.path)
}

// Path returns the config file path
func (cfg *Config) Path() string {
	return cfg.path
}

// SetPath sets where the config file is saved to (a full path)
func (cfg *Config) SetPath(p string) {
	cfg.path = p
}
